/**
 * @param {string} s
 * @param {string} p
 * @return {boolean}
 */
var articleMatch = function(s, p) {
    const sLen = s.length, pLen = p.length;
    const dp = Array.from({ length: sLen + 1 }, () => Array.from({ length: pLen + 1 }, () => false));
    dp[0][0] = true; // 空字符串和空模式可以匹配
    for (let i = 0; i <= sLen; i++) {
        for (let j = 1; j <= pLen; j++) {
            if (p[j - 1] === '*') {
                // 如果模式 p 的第 j 个字符是 *，那么它可以和它前面的字符一起消失，也可以重复出现多次
                dp[i][j] = dp[i][j - 2] || (i > 0 && (s[i - 1] === p[j - 2] || p[j - 2] === '.') && dp[i - 1][j]);
            } else {
                // 如果模式 p 的第 j 个字符不是 *，那么它必须和字符串 s 的第 i 个字符匹配
                dp[i][j] = i > 0 && dp[i - 1][j - 1] && (s[i - 1] === p[j - 1] || p[j - 1] === '.');
            }
        }
    }
    return dp[sLen][pLen]; // 返回最终的匹配结果
};

// 测试用例
const article = "ab";
const input = ".*";
console.log(articleMatch(article, input));